home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / networke / xfirepow.000 / xfirepow / xfirepower-0.84 / client / libsprite / image.c < prev    next >
C/C++ Source or Header  |  1995-05-23  |  15KB  |  476 lines

  1. #include "allincludes.h"
  2.  
  3. void
  4. W_SetImageDir(dir)
  5.      char *dir;
  6. {
  7.     if(imagedir)
  8.     free(imagedir);
  9.  
  10.     imagedir = malloc(strlen(dir)+256);
  11.     strcpy(imagedir, dir);
  12. }
  13.  
  14. void
  15. W_FreeImage(image)
  16.   W_Image *image;
  17. {
  18.   if(image->loaded) {
  19.     XFreePixmap(W_Display, image->pixmap);
  20.     if(image->clipmask && image->xpm) XFreePixmap(W_Display, image->clipmask);
  21.     image->pixmap = image->clipmask = 0;
  22.   }
  23.  
  24.   image->loaded = 0;
  25.   image->xpm = 0;
  26.   image->frames = 0;
  27. }
  28.  
  29. W_Image *
  30. W_BitmapToImage(width, height, bits)
  31.   unsigned int width, height;
  32.   char *bits;
  33. {
  34.   W_Image *image = (W_Image*)malloc(sizeof(W_Image));
  35.  
  36.   image->clipmask = XCreateBitmapFromData(W_Display, W_Root,
  37.                                               bits, width, height);
  38.   image->pixmap = image->clipmask;
  39.   image->frames = 1;
  40.   if(height % width == 0) {  /* probably has multiple frames [BDyess] */
  41.     image->frames = height / width;
  42.     height /= image->frames;
  43.   }
  44.   image->width = width;
  45.   image->height = height;
  46.   image->xpm = 0;
  47.   image->loaded = 1;
  48.   image->bad = 0;
  49.   image->filename = "";
  50.   return image;
  51. }
  52.  
  53. void check_loaded(image)
  54.      W_Image *image;
  55. {
  56.     if(!(image)->loaded) {
  57.     /* not loaded, autoload [BDyess] */
  58.     if(W_LoadImage(image)) {
  59.         sprintf(imagedir,"%s/%s",imagedir,(image)->filename);
  60.         fprintf(stderr,"Something is very wrong.  I can't find any image to load for %s, and all the alternates fail too.  I'm too bummed to continue.\n", imagedir);
  61.         exit(1);
  62.     }
  63.     }
  64. }
  65.  
  66. /*
  67.    Takes an array of image pointers, NULL terminated, and combines them
  68.    to produce a new image.
  69.  
  70.    All images are written centered, and the combined image is just large 
  71.    enough to hold the largest passed image.  If one image has more frames
  72.    than the others, the largest frame size is used and the smaller frame
  73.    images are replicated over the entire sequence. [BDyess] 
  74. */
  75. W_Image *
  76. W_CreateCombinedImage(imagelist,color)
  77.   W_Image **imagelist;
  78.   W_Color color;
  79. {
  80.   int width = 1, height = 1, frames = 1, i, centerx, centery;
  81.   W_Image **list;
  82.   W_Image *image;
  83.   struct window fakewin;
  84.   int tmpOR;
  85.  
  86.   for(list = imagelist; *list; list++) {
  87.     check_loaded(*list);
  88.     if((*list)->width > width) width = (*list)->width;
  89.     if((*list)->height > height) height = (*list)->height;
  90.     if((*list)->frames > frames) frames = (*list)->frames;
  91.   }
  92.   centerx = width / 2;
  93.   centery = height / 2;
  94.   image = (W_Image*)malloc(sizeof(W_Image));
  95.   image->loaded = 1;
  96.   image->xpm = 1;
  97.   image->bad = 0;
  98.   image->width = width;
  99.   image->height = height;
  100.   image->frames = frames;
  101.   image->filename = "combined image";
  102.   image->pixmap = XCreatePixmap(W_Display, W_Root, width, height * frames,
  103.                                 (unsigned)DefaultDepth(W_Display, W_Screen));
  104.   image->clipmask = None;
  105.   /* clear our new image */
  106.   XFillRectangle(W_Display, image->pixmap, colortable[backColor].contexts[0], 
  107.                  0, 0, width, height * frames);
  108.   tmpOR = useOR;    /* don't want to OR when using W_DrawImage [BDyess] */
  109.   useOR = 0;
  110.   for(list = imagelist; *list; list++) {
  111.     for(i=0;i < frames; i++) {
  112.       /* copy the frames, one at a time */
  113.       /* use a fake window for code reuse */
  114.       fakewin.drawable = image->pixmap;
  115.       W_DrawImage(W_Window2Void(&fakewin), centerx - (*list)->width / 2,
  116.                             i*height + centery - (*list)->height / 2,
  117.                 i,
  118.                 *list,
  119.                 color);
  120.     }
  121.   }
  122.   useOR = tmpOR;
  123. /*  printf("created composite image: width %d, height %d, frames %d.\n",
  124.          width,height,frames);*/
  125.   return image;
  126. }
  127.  
  128. int
  129. W_LoadImage(image)
  130.   W_Image *image;
  131. {
  132.   XpmAttributes attributes;
  133.   int ErrorStatus;
  134.   char *warn = NULL, *error = NULL;
  135.   char buf[BUFSIZ];
  136.   static char *imagedirend=NULL;
  137.  
  138.   if(!imagedir)
  139.       W_SetImageDir(".");
  140.  
  141.   if(!image->compiled_in || verbose_image_loading) {
  142.     sprintf(buf,"%s %s...",image->compiled_in ? "Storing" : "Loading",
  143.             image->filename);
  144. /*    warning(buf);*/
  145.     if(verbose_image_loading) {
  146.       puts(buf);
  147.       fflush(stdout);
  148.     }
  149.   }
  150.   if(imagedirend == NULL) imagedirend = imagedir + strlen(imagedir);
  151.  
  152.   if(image->loaded) return 0;
  153.   if(xpm) {
  154.     attributes.valuemask = XpmCloseness|XpmReturnExtensions|XpmColormap;
  155. #ifdef HACKED_XPMLIB
  156.     if(useOR) {
  157.       if (nallocated_colors>=0) {
  158.       attributes.valuemask |= XpmColorFunction;
  159.       attributes.color_allocator = SetColor;
  160.       }
  161.     }
  162. #endif /*HACKED_XPMLIB*/
  163.     attributes.extensions = NULL;
  164.     attributes.colormap = W_Colormap;
  165.     /* take colors that are close [BDyess] */
  166.     attributes.closeness = 40000;
  167.  
  168.     sprintf(imagedirend,"%s.xpm",image->filename);
  169.     if(image->compiled_in) {
  170.       if(image->xpmdata) {
  171.     ErrorStatus = XpmCreatePixmapFromData(W_Display, W_Root, image->xpmdata,
  172.                 &image->pixmap, &image->clipmask, &attributes);
  173.       } else { /* fool the rest of the code into thinking that it is xpm mode
  174.           but loading the xpm failed */
  175.     error = "";
  176.     ErrorStatus = XpmOpenFailed;
  177.       }
  178.     } else {
  179.       ErrorStatus = XpmReadFileToPixmap(W_Display, W_Root, imagedir, 
  180.                 &image->pixmap, &image->clipmask, &attributes);
  181.     }
  182.     switch (ErrorStatus) {
  183.       case XpmColorError:
  184.       warn = "Could not parse or alloc requested color";
  185.       break;
  186.       case XpmOpenFailed:
  187.       error = "Cannot open file";
  188.       break;
  189.       case XpmFileInvalid:
  190.       error = "Invalid XPM file";
  191.       break;
  192.       case XpmNoMemory:
  193.       error = "Not enough memory";
  194.       break;
  195.       case XpmColorFailed:
  196.       error = "Failed to parse or alloc some color";
  197.       break;
  198.     }
  199.   } else { /* fool the rest of the code into thinking that it is xpm mode
  200.               but loading the xpm failed */
  201.     error = "";
  202.     ErrorStatus = XpmOpenFailed;
  203.   }
  204.  
  205.   if (error) {
  206.     if(ErrorStatus != XpmOpenFailed) {
  207.       printf("Error reading in %s: %s.\n", imagedir, error);
  208.     }
  209.     /* ok, can't find or load the xpm, try the xbm [BDyess] */
  210.     if(image->compiled_in) {
  211.       if(image->xbmdata) {
  212.     image->clipmask = XCreateBitmapFromData(W_Display, W_Root, 
  213.                       image->xbmdata, image->width, image->height);
  214.         ErrorStatus = BitmapSuccess;
  215.       } else {
  216.         ErrorStatus = !BitmapSuccess;
  217.       }
  218.     } else {
  219.       sprintf(imagedirend,"%s.xbm",image->filename);
  220.       ErrorStatus = XReadBitmapFile(W_Display, W_Root, imagedir, 
  221.          &image->width, &image->height, &image->clipmask, NULL, NULL);
  222.     }
  223.     if(ErrorStatus != BitmapSuccess) {
  224.       printf("Bitmap read failed for %s.\n",imagedir);
  225.       /*abort();*/
  226.       return 1;        /* let the calling function handle it [BDyess]*/
  227.     }
  228.     if(verbose_image_loading) printf("xbm\n");
  229.     /* bitmap loaded successfully */
  230.     image->loaded = 1;
  231.     image->pixmap = image->clipmask;
  232.     if(image->frames == 0) {
  233.     /* if an image doesn't have a number of frames, then guess how many there
  234.        are by assuming that a frame is square.  This is easily overriden by
  235.        setting frames = 1. [BDyess] */
  236.       if((image->height % image->width) == 0) {   /* even multiple */
  237.         image->frames = image->height / image->width;
  238.       } else {
  239.         image->frames = 1;
  240.       }
  241.     }
  242.     image->height /= image->frames;
  243.     image->xpm = 0;
  244.     return 0;
  245.   }
  246.   if(verbose_image_loading) printf("xpm\n");
  247.   if (warn)
  248.       printf("Warning reading in %s: %s.\n", imagedir, warn);
  249.   /* ok, xpm loaded successfully.  Lets store the data and get outta here
  250.      [BDyess] */
  251.   image->loaded = 1;
  252.   image->xpm = 1;
  253.   image->width = attributes.width;
  254.   /* check for an extension that changes the number of frames [BDyess] */
  255.   if(attributes.extensions) {
  256.     int i;
  257.  
  258.     for (i=0; i<attributes.nextensions; i++) {
  259.     if (0==strcmp("num_views", attributes.extensions[i].name))
  260.         break;
  261.     if (0==strcmp("nviews", attributes.extensions[i].name))
  262.         break;
  263.     }
  264.     if (i<attributes.nextensions) {
  265.       image->frames = atoi(attributes.extensions[i].lines[0]);
  266.     }
  267.   }
  268.   if(image->frames == 0) {
  269.   /* if an image doesn't have a number of frames, then guess how many there
  270.      are by assuming that a frame is square.  This is easily overriden by
  271.      setting frames = 1. [BDyess] */
  272.     if((attributes.height % attributes.width) == 0) {   /* even multiple */
  273.       image->frames = attributes.height / attributes.width;
  274.     } else {
  275.       image->frames = 1;
  276.     }
  277.   }
  278.   image->height = attributes.height / image->frames;
  279.   return 0;
  280.  
  281. /* same as W_DrawImage except that clipmask is not used [BDyess] */
  282. void
  283. W_DrawImageNoClip(window, x, y, frame, image, color)
  284.   W_Window window;
  285.   int x,y,frame;
  286.   W_Image *image;
  287.   W_Color color;
  288. {
  289.   check_loaded(image);
  290.   frame = frame % image->frames;
  291.   if(xpm) {
  292.     if(image->xpm) {
  293.       XSetClipMask(W_Display, colortable[W_Black].contexts[BITMASKGC], 
  294.            None);
  295.       XCopyArea(W_Display, image->pixmap, W_Void2Window(window)->drawable,
  296.      colortable[W_Black].contexts[BITMASKGC], 0,
  297.      (int)(image->height * frame), image->width, image->height, x, y);
  298.     } else {
  299.       XSetClipMask(W_Display, colortable[color].contexts[BITMASKGC], 
  300.            None);
  301.       XCopyPlane(W_Display, image->pixmap, W_Void2Window(window)->drawable,
  302.        colortable[color].contexts[BITMASKGC], 0, 
  303.        (int)(image->height * frame), 
  304.        image->width, image->height, x, y, 1);
  305.     }
  306.   } else {    
  307.     if(image->xpm)
  308.       XCopyArea(W_Display, image->pixmap, W_Void2Window(window)->drawable,
  309.        colortable[color].contexts[BITGC], 0,
  310.        (int)(image->height * frame), image->width, image->height, x, y);
  311.     else
  312.       XCopyPlane(W_Display, image->pixmap, W_Void2Window(window)->drawable,
  313.        colortable[color].contexts[BITGC], 0, 
  314.        (int)(image->height * frame), 
  315.        image->width, image->height, x, y, 1);
  316.   }
  317. }
  318.  
  319. /* similar to W_DrawImage except the clipmask used for image is the sum of the
  320.    clipmasks for image and clipimage.  Currently this is only used for cloaking.
  321.    [BDyess] */
  322. void
  323. W_OverlayImage(window, x, y, frame, image, overframe, overimage,color)
  324.   W_Window window;
  325.   int x,y,frame;
  326.   W_Image *image;
  327.   int overframe;
  328.   W_Image *overimage;
  329.   W_Color color;
  330. {
  331.   int width, height;
  332.   Pixmap workarea;
  333.   struct window foolwin;
  334.   int tmpOR;
  335.  
  336.   check_loaded(image);
  337.   check_loaded(overimage);
  338.   width = image->width > overimage->width ? image->width : overimage->width;
  339.   height =image->height > overimage->height ? image->height : overimage->height;
  340.   frame = frame % image->frames;
  341.   overframe = overframe % overimage->frames;
  342.  
  343.   /* create a temporary offscreen working area [BDyess] */
  344.   workarea = XCreatePixmap(W_Display, W_Root, width, height, 
  345.                            DefaultDepth(W_Display, W_Screen));
  346.   /* fool other routines that want a window into using the work area [BDyess] */
  347.   foolwin.drawable = workarea;
  348.   
  349.   /* copy the first image there [BDyess] */
  350.   W_DrawImageNoClip(W_Window2Void(&foolwin), 
  351.                    (width - image->width) / 2, 
  352.            (height - image->height) / 2, 
  353.            frame, image, color);
  354.  
  355.   /* copy the second image over it [BDyess] */
  356.   /* don't want to use OR... [BDyess] */
  357.   tmpOR = useOR;
  358.   useOR = 0;
  359.   W_DrawImage(W_Window2Void(&foolwin), 
  360.               (width - overimage->width) / 2,
  361.           (height - overimage->height) / 2, 
  362.           overframe, overimage, color);
  363.   useOR = tmpOR;
  364.  
  365.   /* display the work area [BDyess] */
  366.   if(xpm && !useOR) {
  367.       XSetClipOrigin(W_Display, colortable[W_Black].contexts[BITMASKGC], x, 
  368.              (int)(y - (image->height * frame)));
  369.       XSetClipMask(W_Display, colortable[W_Black].contexts[BITMASKGC], 
  370.            image->clipmask);
  371.       XCopyArea(W_Display, workarea, W_Void2Window(window)->drawable,
  372.      colortable[W_Black].contexts[BITMASKGC], 0, 0, width, height, 
  373.      x - (width - image->width) / 2, 
  374.      y - (height - image->height) / 2);
  375.   } else {    
  376.       XCopyArea(W_Display, workarea, W_Void2Window(window)->drawable,
  377.        colortable[color].contexts[BITGC], 0, 0, width, height, x, y);
  378.   }
  379.  
  380.   /* clean up [BDyess] */
  381.   XFreePixmap(W_Display, workarea);
  382. }
  383.   
  384. void
  385. W_DrawImage(window, x, y, frame, image, color)
  386.   W_Window window;
  387.   int x,y,frame;
  388.   W_Image *image;
  389.   W_Color color;
  390. {
  391.   int height, width;
  392.  
  393.   check_loaded(image);
  394.   if(frame < 0) {    /* draw the whole thing regardless of frames [BDyess] */
  395.     height = image->height * image->frames;
  396.     frame = 0;
  397.   } else {        /* draw the frame given [BDyess] */
  398.     height = image->height;
  399.     frame = frame % image->frames;
  400.   }
  401.   width = image->width;
  402.   if(xpm && !useOR) {
  403.     if(image->xpm) {
  404.       XSetClipOrigin(W_Display, colortable[color].contexts[BITMASKGC], x,
  405.              (int)(y - (height * frame)));
  406.       XSetClipMask(W_Display, colortable[color].contexts[BITMASKGC],
  407.            image->clipmask);
  408.       XCopyArea(W_Display, image->pixmap, W_Void2Window(window)->drawable,
  409.      colortable[color].contexts[BITMASKGC], 0,
  410.      (int)(height * frame), width, height, x, y);
  411.     } else {
  412.       XSetClipOrigin(W_Display, colortable[color].contexts[BITMASKGC], x, 
  413.              (int)(y - (height * frame)));
  414.       XSetClipMask(W_Display, colortable[color].contexts[BITMASKGC], 
  415.            image->clipmask);
  416.       XCopyPlane(W_Display, image->pixmap, W_Void2Window(window)->drawable,
  417.        colortable[color].contexts[BITMASKGC], 0, 
  418.        (int)(height * frame), 
  419.        width, height, x, y, 1);
  420.     }
  421.   } else {    
  422.     if(image->xpm) {
  423.       XCopyPlane(W_Display, image->clipmask, W_Void2Window(window)->drawable,
  424.        maskGC, 0,
  425.        (int)(height * frame), 
  426.        width, height, x, y, 1);
  427.       XCopyArea(W_Display, image->pixmap, W_Void2Window(window)->drawable,
  428.        colortable[color].contexts[BITGC], 0,
  429.        (int)(height * frame), width, height, x, y);
  430.     } else
  431.       XCopyPlane(W_Display, image->pixmap, W_Void2Window(window)->drawable,
  432.        colortable[color].contexts[BITGC], 0, 
  433.        (int)(height * frame), 
  434.        width, height, x, y, 1);
  435.   }
  436. }
  437.  
  438. /* same as W_DrawImage except image is drawn using GXor instead of GXcopy 
  439.    [BDyess] */
  440. void
  441. W_DrawImageOr(window, x, y, frame, image, color)
  442.   W_Window window;
  443.   int x,y,frame;
  444.   W_Image *image;
  445.   W_Color color;
  446. {
  447.   check_loaded(image);
  448.   frame = frame % image->frames;
  449.   if(image->xpm) {
  450.       XCopyArea(W_Display, image->pixmap, W_Void2Window(window)->drawable,
  451.      colortable[W_Black].contexts[BITGC], 0,
  452.      (int)(image->height * frame), image->width, image->height, x, y);
  453.   } else {    
  454.     XCopyPlane(W_Display, image->pixmap, W_Void2Window(window)->drawable,
  455.      colortable[color].contexts[BITGC], 0, 
  456.      (int)(image->height * frame), 
  457.      image->width, image->height, x, y, 1);
  458.   }
  459. }
  460.  
  461.  
  462. void
  463. W_DrawImageBar(win, x, y, len, image)
  464.   W_Window win;
  465.   int x,y,len;
  466.   W_Image *image;
  467. {
  468.    if(len == 0) return;
  469.    XSetClipMask(W_Display,colortable[W_Black].contexts[BITMASKGC],None);
  470.    XCopyArea(W_Display, image->pixmap, W_Void2Window(win)->drawable,
  471.        colortable[W_Black].contexts[BITMASKGC], 0, 0, 
  472.        (unsigned)len+1, image->height, x, y);
  473. }
  474.  
  475.